package com.teen9g.infoplatformserver.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.hash.BloomFilter;
import com.teen9g.PageQueryDTO.CanteenShopPageQueryDTO;
import com.teen9g.PageQueryDTO.CanteenShopUserPageQueryDTO;
import com.teen9g.constant.CategoryConstant;
import com.teen9g.constant.RedisKey;
import com.teen9g.context.BaseContext;
import com.teen9g.dto.CanteenShopDTO;
import com.teen9g.entity.CanteenShop;
import com.teen9g.entity.SingleRecentEdit;
import com.teen9g.exception.CanteenShopNotFoundException;
import com.teen9g.infoplatformserver.mapper.CanteenShopMapper;
import com.teen9g.infoplatformserver.mapper.RecentEditMapper;
import com.teen9g.infoplatformserver.mapper.UserMapper;
import com.teen9g.infoplatformserver.service.CanteenShopService;
import com.teen9g.userVO.CanteenShopUserVO;
import com.teen9g.utils.StringUtil;
import com.teen9g.vo.CanteenShopVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class CanteenShopServiceImpl implements CanteenShopService {
    @Autowired
    private CanteenShopMapper canteenShopMapper;

    @Autowired
    private RecentEditMapper recentEditMapper;

    @Autowired
    private RedisTemplate<String, Long> redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private BloomFilter<Integer> canteenShopBloomFilter;

    @Autowired
    private RedisTemplate<String, CanteenShop> canteenShopRedisTemplate;

    @Autowired
    private RedisTemplate<String, String> StringRedisTemplate;
    /**
     * 食堂商铺分页查询
     *
     * @param pageQueryDTO 分页查询条件
     * @return 分页查询结果
     */
    @Override
    public PageInfo<CanteenShopVO> pageQuery(CanteenShopPageQueryDTO pageQueryDTO) {
        PageHelper.startPage(pageQueryDTO.getPageNum(), pageQueryDTO.getPageSize());
        List<CanteenShopVO> list = canteenShopMapper.selectByPage(pageQueryDTO);
        return new PageInfo<>(list);
    }

    /**
     * 食堂商铺分页查询
     *
     * @param pageQueryDTO 分页查询条件
     * @return 分页查询结果
     */
    @Override
    public PageInfo<CanteenShopUserVO> pageQueryByUserId(CanteenShopUserPageQueryDTO pageQueryDTO) {
        PageHelper.startPage(pageQueryDTO.getPageNum(), pageQueryDTO.getPageSize());
        List<CanteenShopUserVO> list = canteenShopMapper.selectByPageByUserId(pageQueryDTO);
        return new PageInfo<>(list);
    }


    /**
     * 添加食堂商铺
     *
     * @param canteenShopDTO 食堂商铺
     * @return 添加结果
     */
    @Override
    public int add(CanteenShopDTO canteenShopDTO) {
        //先获取Author对象
        String shopAuthor = BaseContext.getCurrentUser();
        //将各个属性封装到CanteenShop对象中
        CanteenShop canteenShop = CanteenShop.builder()
                .shopName(canteenShopDTO.getShopName())
                .shopAt(canteenShopDTO.getShopAt())
                .shopFloor(canteenShopDTO.getShopFloor())
                .shopRelativePosition(canteenShopDTO.getShopRelativePosition())
                .shopDescription(canteenShopDTO.getShopDescription())
                .shopImage(canteenShopDTO.getShopImage())
                .shopPayment(canteenShopDTO.getShopPayment())
                .shopAuthor(shopAuthor)
                .shopAuthorAvatarUrl(userMapper.getAvatarUrlByUserId(BaseContext.getCurrentUserId()))
                .shopRecentEditor(shopAuthor)
                .shopCreateTime(LocalDateTime.now())
                .shopUpdateTime(LocalDateTime.now())
                .build();
        //将CanteenShop对象插入到数据库中
        return canteenShopMapper.insert(canteenShop);
    }

    /**
     * 初步展示页获取所有食堂店铺
     *
     * @return 所有食堂店铺
     */
    @Override
    public List<CanteenShopVO> getAllFront() {
        return canteenShopMapper.selectListFront();
    }

    /**
     * 根据id获取食堂店铺
     *
     * @param shopId 食堂店铺id
     * @return 食堂店铺
     */
    @Override
    public CanteenShop getById(Integer shopId) {
        //先判断shopId是否存在布隆过滤器中
        if (!canteenShopBloomFilter.mightContain(shopId)) {
            return null;
        }
        //走一下Redis
        String key = RedisKey.CS_KEY_PREFIX + shopId;
        CanteenShop canteenShop = canteenShopRedisTemplate.opsForValue().get(key);
        if (canteenShop != null) {
            return canteenShop;
        }

        //Redis为空，再走数据库，并将数据存入Redis
        canteenShop = canteenShopMapper.selectById(shopId);
        if (canteenShop != null) {
            //将店铺信息存入Redis
            canteenShopRedisTemplate.opsForValue().set
                    (key, canteenShop, RedisKey.CS_EXPIRE_TIME, TimeUnit.MINUTES);
            //把作者的头像单独查出来存入实体
            Long shopAuthorId = redisTemplate.opsForValue().get(canteenShop.getShopAuthor());
            //作者id缓存为空的情况
            if (shopAuthorId == null) {
                shopAuthorId = userMapper.getUserIdByUsername(canteenShop.getShopAuthor());
                redisTemplate.opsForValue().set(canteenShop.getShopAuthor(), shopAuthorId, RedisKey.USER_CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
            }
            String avatarUrl = StringRedisTemplate.opsForValue().get(RedisKey.USER_KEY_AVATAR_PREFIX + shopAuthorId);
            //头像url缓存为空的情况
            if (avatarUrl == null) {
                avatarUrl = userMapper.getAvatarUrlByUserId(Math.toIntExact(shopAuthorId));
                StringRedisTemplate.opsForValue().set
                        (RedisKey.USER_KEY_AVATAR_PREFIX + shopAuthorId, avatarUrl, RedisKey.USER_CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
            }
            canteenShop.setShopAuthorAvatarUrl(avatarUrl);
        }

        return canteenShop;
    }

    @Override
    public void addView(Integer shopId) {
        String key = RedisKey.CS_VIEW_KEY + shopId;
        redisTemplate.opsForValue().increment(key);
    }


    /**
     * 初步展示页获取所有一食堂店铺
     *
     * @return 所有一食堂店铺
     */
    @Override
    public List<CanteenShopVO> getFirstAllFront() {
        return canteenShopMapper.selectFirstAllFront();
    }

    /**
     * 初步展示页获取所有二食堂店铺
     *
     * @return 所有二食堂店铺
     */
    @Override
    public List<CanteenShopVO> getSecondAllFront() {
        return canteenShopMapper.selectSecondAllFront();
    }

    /**
     * 修改食堂商铺
     *
     * @param canteenShopDTO 食堂商铺
     * @param id             食堂商铺id
     * @return 修改结果
     */
    @Override
    public int update(CanteenShopDTO canteenShopDTO, Integer id) {
        //先判断传入的修改对象是否为空
        if (canteenShopDTO == null) {
            return -1;
        }
        //先获取原实体，判断原实体是否存在
        CanteenShop canteenShop = canteenShopMapper.selectById(id);
        if (canteenShop == null) {
            throw new CanteenShopNotFoundException("食堂店铺不存在");
        }
        //先再判断修改了什么内容
        CanteenShopDTO tempDTO = new CanteenShopDTO();
        BeanUtils.copyProperties(canteenShop, tempDTO);
        StringUtil stringUtil = new StringUtil();
        String operation = stringUtil.CS_getOperation(tempDTO, canteenShopDTO);
        //拷贝参数
        BeanUtils.copyProperties(canteenShopDTO, canteenShop);
        //设置更新时间
        canteenShop.setShopUpdateTime(LocalDateTime.now());
        //设置最近编辑人
        canteenShop.setShopRecentEditor(BaseContext.getCurrentUser());
        //更新最近编辑表(insert)
        if (!operation.isEmpty()) {
            SingleRecentEdit singleRecentEdit = SingleRecentEdit.builder()
                    .updateEditor(BaseContext.getCurrentUser())
                    .updateTime(LocalDateTime.now())
                    .contentCategory(CategoryConstant.CANTEEN_SHOP)
                    .contentId(id)
                    .contentTitle(canteenShop.getShopName())
                    .updateOperation(operation)
                    .build();
            recentEditMapper.insert(singleRecentEdit);
        }
        //更新食堂店铺数据库
        return canteenShopMapper.updateById(canteenShop);
    }

    /**
     * 删除食堂商铺
     *
     * @param id 食堂商铺id
     * @return 删除结果
     */
    @Override
    public int delete(Integer id) {
        return canteenShopMapper.deleteById(id);
    }


}
